﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Cofe.Core;
using Cofe.Core.EntryType;
using Cofe.Core.Property;
using Cofe.Core.Utils;
using Cofe.IO;
using Cofe.IO.Interfaces;
#if !NETFX_CORE
using System.Drawing;
using System.Windows.Media.Imaging;
using Cofe.Core.Utils;
using Cofe.Shell;
using System.Threading;
#endif

namespace Cofe.IO.Implements
{
    #if !NETFX_CORE
    [Export(typeof(ICofeService))]
    [ServicePriority(ServicePriorityAttribute.DefaultPriority_COFEIO)]
    public class SystemIOEntryTypeProvider : IEntryTypeIdentifier, IEntryTypeInfoProvider
    {
        public const string KeyPrefix = "SystemIO_";
        public const string DirectoryKey = KeyPrefix + "directory";
        #region Constructor

        #endregion

        #region Methods

        public string GetEntryTypeKey(IPropertyHost propertyHost)
        {
            if (propertyHost.PrimaryPropertyProvider is IFSIPropertyProvider)
            {
                string type = propertyHost.Behaviors.GetProperty(CofeProperties.Type).ValueAsString;
                if (type.ToLower() == "file")
                {
                    string name = propertyHost.Behaviors.GetProperty(CofeProperties.Name).ValueAsString;
                    return KeyPrefix + PathFE.GetExtension(name.ToLower()).TrimStart('.');
                }
                else return DirectoryKey;
            }
            else return null;
        }

        public Task<PropertyPair[]> GetEntryTypeInfoAsync(string entryTypeKey)
        {
            if (entryTypeKey.StartsWith(KeyPrefix))
            {
                List<PropertyPair> retVal = new List<PropertyPair>();

                string type =  entryTypeKey == DirectoryKey ? 
                    "directory" : 
                    "." + entryTypeKey.Replace(KeyPrefix, "").ToLower();
                string fileType, mimetype;
                if (type == "directory")
                {
                    retVal.Add(PropertyPair.FromValue(FileTypeInfoProperties.FileTypeDescription, RegistryUtils.GetDirectoryDescription()));                    
                }
                else
                {
                   
                    RegistryUtils.GetTypeInformation(type, out fileType, out mimetype);
                    //fileType = fileType.TrimStart('.');
                    retVal.Add(PropertyPair.FromValue(FileTypeInfoProperties.FileTypeDescription, RegistryUtils.GetFileDescription()));
                    retVal.Add(PropertyPair.FromValue(FileTypeInfoProperties.FileType, fileType));
                    retVal.Add(PropertyPair.FromValue(FileTypeInfoProperties.MIMEType, mimetype));                   
                }

                retVal.Add(PropertyPair.FromValueFunc(CofeIconProperties.SmallIcon, () => getIconStreamAsync(CofeIconProperties.SmallIcon, type).Result, false, false));
                retVal.Add(PropertyPair.FromValueFunc(CofeIconProperties.LargeIcon, () => getIconStreamAsync(CofeIconProperties.LargeIcon, type).Result, false, false));
                retVal.Add(PropertyPair.FromValueFunc(CofeIconProperties.ExtraLargeIcon, () => getIconStreamAsync(CofeIconProperties.ExtraLargeIcon, type).Result, false, false));
                retVal.Add(PropertyPair.FromValueFunc(CofeIconProperties.JumboIcon, () => getIconStreamAsync(CofeIconProperties.JumboIcon, type).Result, false, false));                    

                return Task.FromResult<PropertyPair[]>(retVal.ToArray());
            }

            return Task.FromResult<PropertyPair[]>(null); ;
        }

        private static Semaphore imgListLock = new Semaphore(1,1);

        private Task<BitmapContainer> getIconStreamAsync(CofeIconProperties prop, string ext)
        {
            IconSize size = IconSize.large;
            switch ((int)prop)
            {
                case (int)CofeIconProperties.SmallIcon: size = IconSize.small; break;
                case (int)CofeIconProperties.LargeIcon: size = IconSize.large; break;
                case (int)CofeIconProperties.ExtraLargeIcon: size = IconSize.extraLarge; break;
                case (int)CofeIconProperties.JumboIcon: size = IconSize.jumbo; break;
            }            

            Bitmap bitmap;
            
            imgListLock.WaitOne(TimeSpan.FromSeconds(5));
            try
            {
                using (var imgList = new SystemImageList(size))
                {
                    if (ext == "directory")
                        bitmap = imgList["", true, false];
                    else
                    {
                        bitmap = imgList["AAA" + ext, false, false];
                    }
                }
            }
            finally
            {
                imgListLock.Release();
            }
            bitmap = IconPropertiesExtension.EnsureBitmapSize(bitmap, prop);

            var retVal = BitmapContainer.FromBitmap(bitmap, null, prop);
            retVal.DisposeEntity = false;

            return Task.FromResult<BitmapContainer>(retVal);
        }

        #endregion

        #region Data

        #endregion

        #region Public Properties

        #endregion
    }
#endif
}
